package middleware

import (
	"blog-server/global"
	"blog-server/models"
	"errors"
	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"net/http"
	"strings"
	"time"
)

type BlogClaims struct {
	models.User
	jwt.StandardClaims
}

// Jwt jwt鉴权控制
func Jwt() gin.HandlerFunc {
	return func(c *gin.Context) {
		token := c.Request.Header.Get("Authorization")
		// 先判空
		if token == "" {
			c.JSON(http.StatusOK, gin.H{
				"code": 2003,
				"msg":  "请求头中auth为空",
			})
			c.Abort()
			return
		}
		// 判断token的前缀是否正确
		items := strings.SplitN(token, " ", 2)
		if !(len(items) == 2 && items[0] == "Blog") {
			c.JSON(http.StatusOK, gin.H{
				"code": 2004,
				"msg":  "请求头中auth格式有误",
			})
			c.Abort()
			return
		}
		// 解析token信息
		blogClaims, err := ParseToken(items[1])
		if err != nil {
			c.JSON(http.StatusOK, gin.H{
				"code": 2005,
				"msg":  "无效的Token",
			})
			c.Abort()
			return
		}
		c.Set("userInfo", blogClaims.User)
		c.Next()
	}
}

// GenToken 构建Token
func GenToken(u models.User) (string, error) {

	c := BlogClaims{
		u,
		jwt.StandardClaims{
			NotBefore: time.Now().Unix(),
			ExpiresAt: time.Now().Unix() + global.Config.JWT.ExpiresTime,
			Issuer:    global.Config.JWT.Issuer,
		},
	}
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, c)
	return token.SignedString([]byte(global.Config.JWT.SignKey))
}

// ParseToken 解析token
func ParseToken(tokenString string) (*BlogClaims, error) {
	token, err := jwt.ParseWithClaims(tokenString, &BlogClaims{}, func(token *jwt.Token) (interface{}, error) {
		return []byte(global.Config.JWT.SignKey), nil
	})
	if err != nil {
		return nil, err
	}

	if claims, ok := token.Claims.(*BlogClaims); ok && token.Valid {
		return claims, nil
	}
	return nil, errors.New("非法的Token串")
}
